home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Xconq 7.0d37 / source / kernel / skelconq.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-25  |  25.2 KB  |  1,170 lines  |  [TEXT/KAHL]

  1. /* A minimal interface to Xconq.
  2.    Copyright (C) 1991, 1992, 1993, 1994, 1995 Stanley T. Shebs.
  3.  
  4. Xconq is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.  See the file COPYING.  */
  8.  
  9. /* This interface uses only what is
  10.    required by ANSI, so it should run just about everywhere without
  11.    any changes.  This is most useful for testing the kernel and game
  12.    design libraries.
  13.  
  14.    This file can also serve as a starting point for writing a new interface,
  15.    since it has simple or default implementations of the routines that any
  16.    interface has to support. */
  17.  
  18. #ifndef USE_CONSOLE
  19. #define USE_CONSOLE
  20. #endif
  21.  
  22. #include "conq.h"
  23. #include "print.h"
  24. #include "cmdline.h"
  25.  
  26. #ifdef COMPILER
  27. extern void compile PROTO ((void));
  28. #endif /* COMPILER */
  29.  
  30. static void init_displays PROTO ((void));
  31. static void get_input PROTO ((void));
  32. static void interpret_command PROTO ((Obj *cmd));
  33. static void list_one_unit PROTO ((Unit *unit));
  34. static void interpret_help PROTO ((Side *side, char *str));
  35. static int do_cmd PROTO ((Side *side, Obj *cmd, Obj *parms));
  36. #ifdef DEBUGGING
  37. static void toggle_debug PROTO ((Side *side, Obj *cmd, Obj *parms));
  38. static void toggle_debugg PROTO ((Side *side, Obj *cmd, Obj *parms));
  39. static void toggle_debugm PROTO ((Side *side, Obj *cmd, Obj *parms));
  40. #endif /* DEBUGGING */
  41. static void list_sides PROTO ((Side *side, Obj *cmd, Obj *parms));
  42. static void list_units PROTO ((Side *side, Obj *cmd, Obj *parms));
  43. static void list_actors PROTO ((Side *side, Obj *cmd, Obj *parms));
  44. static void list_cells PROTO ((Side *side, Obj *cmd, Obj *parms));
  45. static void do_task_cmd PROTO ((Side *side, Obj *cmd, Obj *parms));
  46. static void do_finish_turn PROTO ((Side *side, Obj *cmd, Obj *parms));
  47. static void do_finish_all PROTO ((Side *side, Obj *cmd, Obj *parms));
  48. static void do_repeat PROTO ((Side *side, Obj *cmd, Obj *parms));
  49. static void do_multiple PROTO ((Side *side, Obj *cmd, Obj *parms));
  50. static void do_free_run PROTO ((Side *side, Obj *cmd, Obj *parms));
  51. static void do_save PROTO ((Side *side, Obj *cmd, Obj *parms));
  52. static void do_eval PROTO ((Side *side, Obj *cmd, Obj *parms));
  53. static void do_help PROTO ((Side *side, Obj *cmd, Obj *parms));
  54. static void do_print PROTO ((Side *side, Obj *cmd, Obj *parms));
  55. static void do_memory PROTO ((Side *side, Obj *cmd, Obj *parms));
  56. static void do_quit PROTO ((Side *side, Obj *cmd, Obj *parms));
  57. static int do_action PROTO ((Side *side, Unit *unit, Obj *cmd, Obj *args));
  58. static void show_help PROTO ((Side *side, HelpNode *node));
  59. static void describe_commands PROTO ((int, char *, char *));
  60.  
  61. #ifdef THINK_C
  62. /* This is to get the command line reader in Think C on the Mac. */
  63. #include <console.h>
  64. #endif /* THINK_C */
  65.  
  66. #ifdef THINK_C
  67. /* Think C loses on the compiler. */
  68. #undef COMPILER
  69. #endif /* THINK_C */
  70.  
  71. /* This structure maintains state that is local to a side's display.
  72.    At the very least, it should track when the display is open and closed. */
  73.  
  74. typedef struct a_ui {
  75.     int active;
  76. } UI;
  77.  
  78. Side *defaultside = NULL;
  79.  
  80. HelpNode *curhelpnode;
  81.  
  82. int freerunturns = 0;
  83.  
  84. int repetition = 0;
  85.  
  86. Obj *multicmd = NULL;
  87.  
  88. time_t skelturnstart;
  89.  
  90. int numcellupdatesperturn = 0;
  91.  
  92. int numusefulcellupdatesperturn = 0;
  93.  
  94. /* The main program just calls the setup routines, then enters an infinite
  95.    loop interpreting input and running the simulation. */
  96.  
  97. int
  98. main(argc, argv)
  99. int argc;
  100. char *argv[];
  101. {
  102.     extern long initrandstate, randstate;
  103.     long currandstate;
  104.  
  105. #ifdef THINK_C
  106.     /* This is how Think C picks up a command line. */
  107.     argc = ccommand(&argv);
  108. #endif
  109.     printf("Skeleton Xconq version %s\n", version_string());
  110.     printf("(C) %s\n", copyright_string());
  111.     init_library_path(NULL);
  112.     clear_game_modules();
  113.     init_data_structures();
  114.     /* Dump the random state so we can reproduce the run if necessary. */
  115.     printf("Random state is %d", randstate);
  116.     if (initrandstate != randstate) {
  117.     printf(" (seed was %d)", initrandstate);
  118.     }
  119.     printf("\n");
  120.     currandstate = randstate;
  121.     parse_command_line(argc, argv, general_options);
  122.     if (currandstate != randstate) {
  123.     printf("Random state is now %d.\n", randstate);
  124.     }
  125.     load_all_modules();
  126.     /* See if we have something resembling a valid game.  A synth method might
  127.        still change some numbers, but it's up to the method to do it right. */
  128.     check_game_validity();
  129.     parse_command_line(argc, argv, variant_options);
  130.     set_variants_from_options();
  131.     parse_command_line(argc, argv, player_options);
  132.     set_players_from_options();
  133.     parse_command_line(argc, argv, leftover_options);
  134.     make_trial_assignments();
  135.     calculate_globals();
  136.     run_synth_methods();
  137.     final_init();
  138.     assign_players_to_sides();
  139.     init_displays();
  140.     init_signal_handlers();
  141.     run_game(0);
  142.     multicmd = lispnil;
  143.     time(&skelturnstart);
  144.     while (1) {
  145.     if (freerunturns > 0) {
  146.         if (probability(1)) {
  147.             printf("No apparent progress, forcing the turn to finish.\n");
  148.             do_finish_all(NULL, lispnil, lispnil);
  149.         }
  150.         if (endofgame)
  151.           freerunturns = 0;
  152.     } else {
  153.         get_input();
  154.     }
  155.     run_game(-1);
  156.     }
  157. }
  158.  
  159. Player *
  160. add_default_player()
  161. {
  162.     Player *dflt = add_player();
  163.  
  164.     dflt->displayname = "stdio";
  165.     Dprintf("Added the default player %s\n", player_desig(dflt));
  166.     return dflt;
  167. }
  168.  
  169. /* This routine handles all the displays that might need to be opened. */
  170.  
  171. static void
  172. init_displays()
  173. {
  174.     Side *side;
  175.  
  176.     for_all_sides(side) {
  177.     if (side_has_display(side)) {
  178.         side->ui->active = TRUE;
  179.         printf("%s now has an open display.\n", side_desig(side));
  180.     }
  181.     }
  182. }
  183.  
  184. /* Create a user interface, but leave it turned off. */
  185.  
  186. void
  187. init_ui(side)
  188. Side *side;
  189. {
  190.     if (side_wants_display(side)) {
  191.         side->ui = (UI *) xmalloc(sizeof(UI));
  192.     /* Display should not become active yet. */
  193.     side->ui->active = FALSE;
  194.     defaultside = side;
  195.     set_autofinish(side, FALSE);
  196.     DGprintf("Created a UI for %s\n", side_desig(side));
  197.     } else {
  198.     side->ui = NULL;
  199.     }
  200. }
  201.  
  202. /* This tests whether the side has a display and if it is in use. */
  203.  
  204. int
  205. active_display(side)
  206. Side *side;
  207. {
  208.     return (side && side_has_display(side) && side->ui->active);
  209. }
  210.  
  211. /* Input reading waits for a number of sides, possibly times out. */
  212.  
  213. static void
  214. get_input()
  215. {
  216.     int cmdlineno = 1, endlineno = 1;
  217.     Obj *cmd;
  218.     Side *side = NULL;
  219.  
  220.     if (realtime_game()) {
  221.     for_all_sides(side) {
  222.         update_clock_display(side, TRUE);
  223.     }
  224.     }
  225.     /* should say which sides we're waiting for */
  226.     printf("> ");
  227.     fflush(stdout);
  228.     if (repetition-- > 0) {
  229.     cmd = multicmd;
  230.     } else {
  231.     cmd = read_form(stdin, &cmdlineno, &endlineno);
  232.     }
  233.     if (cmd != lispeof) {
  234.     Dprintlisp(cmd);
  235.     interpret_command(cmd);
  236.     } else {
  237.     printf("EOF reached\n");
  238.     /* should just close one display, leave others running */
  239.     exit(0);
  240.     }
  241. }
  242.  
  243. Unit *thisunit;
  244.  
  245. /* Do some simple command parsing, just enough to exercise the program. */
  246.  
  247. static void
  248. interpret_command(origcmd)
  249. Obj *origcmd;
  250. {
  251.     char *str;
  252.     Obj *cmd, *verb = lispnil, *parms = lispnil;
  253.     Side *side = NULL;
  254.     Unit *unit = NULL;
  255.  
  256.     thisunit = NULL;
  257.     cmd = origcmd;
  258.     if (consp(cmd) && numberp(car(cmd))) {
  259.     side = side_n(c_number(car(cmd)));
  260.     cmd = cdr(cmd);
  261.     }
  262.     if (consp(cmd) && numberp(car(cmd))) {
  263.     unit = find_unit(c_number(car(cmd)));
  264.     thisunit = unit;
  265.     cmd = cdr(cmd);
  266.     }
  267.     if (consp(cmd)) {
  268.     verb = car(cmd);
  269.     parms = cdr(cmd);
  270.     } else if (symbolp(cmd)) {
  271.     verb = cmd;
  272.     }
  273.     if (verb == lispnil) {
  274.     } else if (do_cmd(side, verb, parms)) {
  275.     } else if (do_action(side, unit, verb, parms)) {
  276.     } else if (symbolp(verb) && *(str = c_string(verb)) == '?') {
  277.     interpret_help(side, str+1);
  278.     } else {
  279.     printf("Command ");
  280.     printlisp(origcmd);
  281.     printf(" not understood, ignoring it\n");
  282.     }
  283. }
  284.  
  285. /* Random commands. */
  286.  
  287. static void
  288. toggle_debug(side, cmd, parms)
  289. Side *side;
  290. Obj *cmd, *parms;
  291. {
  292.     if (parms == lispnil) {
  293.     Debug = !Debug;
  294.     } else if (symbolp(car(parms)) && equal(car(parms), intern_symbol("on"))) {
  295.     Debug = TRUE;
  296.     } else {
  297.     Debug = FALSE;
  298.     }
  299. }
  300.  
  301. static void
  302. toggle_debugm(side, cmd, parms)
  303. Side *side;
  304. Obj *cmd, *parms;
  305. {
  306.     if (parms == lispnil) {
  307.     DebugM = !DebugM;
  308.     } else if (symbolp(car(parms)) && equal(car(parms), intern_symbol("on"))) {
  309.     DebugM = TRUE;
  310.     } else {
  311.     DebugM = FALSE;
  312.     }
  313. }
  314.  
  315. static void
  316. toggle_debugg(side, cmd, parms)
  317. Side *side;
  318. Obj *cmd, *parms;
  319. {
  320.     if (parms == lispnil) {
  321.     DebugG = !DebugG;
  322.     } else if (symbolp(car(parms)) && equal(car(parms), intern_symbol("on"))) {
  323.     DebugG = TRUE;
  324.     } else {
  325.     DebugG = FALSE;
  326.     }
  327. }
  328.  
  329. static void
  330. list_sides(side, cmd, parms)
  331. Side *side;
  332. Obj *cmd, *parms;
  333. {
  334.     int u;
  335.     Side *side2;
  336.     Agreement *ag;
  337.     extern int numagreements;
  338.  
  339.     printf("Sides:\n");
  340.     for_all_sides(side2) {
  341.     printf("%s played by %s\n",
  342.            side_desig(side2), player_desig(side2->player));
  343.     if (using_tech_levels()) {
  344.         printf("Tech:");
  345.         for_all_unit_types(u) {
  346.         if (u_tech_max(u) > 0) {
  347.             printf("  %s %d/%d",
  348.                u_type_name(u), side2->tech[u], u_tech_max(u));
  349.         }
  350.         }
  351.         printf("\n");
  352.     }
  353.     /* (should say something about mplayer goals here) */
  354.     }
  355.     if (numagreements > 0) {
  356.     printf("Agreements:\n");
  357.     for_all_agreements(ag) {
  358.         printf("%s\n", agreement_desig(ag));
  359.     }
  360.     }
  361. }
  362.  
  363. static void
  364. list_units(side, cmd, parms)
  365. Side *side;
  366. Obj *cmd, *parms;
  367. {
  368.     Unit *unit;
  369.  
  370.     printf("Units:\n");
  371.     for_all_units(unit) {
  372.     list_one_unit(unit);
  373.     }
  374. }
  375.  
  376. static void
  377. list_actors(side, cmd, parms)
  378. Side *side;
  379. Obj *cmd, *parms;
  380. {
  381.     int i;
  382.     Side *side2;
  383.     Unit *unit;
  384.     extern UnitVector *actionvector;
  385.  
  386.     printf("Actors (listed by side):\n");
  387.     for_all_sides(side2) {
  388.     printf("%s: %s\n",
  389.            side_desig(side2),
  390.            (side2->finishedturn ? "(finished)" : ""));
  391.     }
  392.     for (i = 0; i < actionvector->numunits; ++i) {
  393.     unit = (actionvector->units)[i].unit;
  394.     list_one_unit(unit);
  395.     }
  396. }
  397.  
  398. static void
  399. list_one_unit(unit)
  400. Unit *unit;
  401. {
  402.     char status[BUFSIZE];
  403.  
  404.     if (unit == NULL) {
  405.     printf("  -\n");
  406.     return;
  407.     }
  408.     if (!completed(unit)) {
  409.     sprintf(status, " cp %d ", unit->cp);
  410.     } else if (unit->hp < u_hp(unit->type)) {
  411.     sprintf(status, " hp %d ", unit->hp);
  412.     } else {
  413.     sprintf(status, " ");
  414.     }
  415.     printf("  %s%s%s %s\n",
  416.        unit_desig(unit), status,
  417.        actorstate_desig(unit->act), plan_desig(unit->plan));
  418. }
  419.  
  420. static void
  421. list_cells(side, cmd, parms)
  422. Side *side;
  423. Obj *cmd, *parms;
  424. {
  425.     int x = c_number(car(parms)), y = c_number(cadr(parms));
  426.  
  427.     printf("At %d,%d", x, y);
  428.     if (in_area(x, y)) {
  429.     printf(", terrain %s", t_type_name(terrain_at(x, y)));
  430.     /* (dump borders?) */
  431.     printf(", elev %d", elev_at(x, y));
  432.     printf(", temp %d", temperature_at(x, y));
  433.     /* (etc) */
  434.     } else {
  435.     printf(" - outside area!");
  436.     }
  437.     printf("\n");
  438. }
  439.  
  440. static void
  441. do_task_cmd(side, cmd, parms)
  442. Side *side;
  443. Obj *cmd, *parms;
  444. {
  445.     int i, j, numargs;
  446.     char *taskname;
  447.     Obj *tasksym = car(parms), *taskparms = cdr(parms);
  448.     Task *task;
  449.  
  450.     if (symbolp(tasksym)) {
  451.     taskname = c_string(tasksym);
  452.     /* Iterate through task names looking for a match. */
  453.     for (i = 0; taskdefns[i].name != NULL; ++i) {
  454.         if (strcmp(taskname, taskdefns[i].name) == 0) {
  455.         if (thisunit != NULL && thisunit->plan != NULL) {
  456.             task = create_task(i);
  457.             numargs = strlen(taskdefns[i].argtypes);
  458.             for (j = 0; j < numargs; ++j) {
  459.             if (taskparms != lispnil) {
  460.                 task->args[j] = c_number(car(taskparms));
  461.                 taskparms = cdr(taskparms);
  462.             } else {
  463.                 task->args[j] = 0;
  464.             }
  465.             }
  466.             task->next = thisunit->plan->tasks;
  467.             thisunit->plan->tasks = task;
  468.             thisunit->plan->waitingfortasks = FALSE;
  469.         }
  470.         return;
  471.         }
  472.     }
  473.     fprintf(stderr, "Task type \"%s\" not recognized\n", taskname);
  474.     }
  475. }
  476.  
  477. static void
  478. do_finish_turn(side, cmd, parms)
  479. Side *side;
  480. Obj *cmd, *parms;
  481. {
  482.     if (side) {
  483.     finish_turn(side);
  484.     } else {
  485.     fprintf(stderr, "No side?\n");
  486.     }
  487. }
  488.  
  489. static void
  490. do_finish_all(side, cmd, parms)
  491. Side *side;
  492. Obj *cmd, *parms;
  493. {
  494.     Side *side2;
  495.  
  496.     for_all_sides(side2) {
  497.     finish_turn(side2);
  498.     }
  499. }
  500.  
  501. static void
  502. do_free_run(side, cmd, parms)
  503. Side *side;
  504. Obj *cmd, *parms;
  505. {
  506.     freerunturns = c_number(car(parms));
  507. }
  508.  
  509. static void
  510. do_repeat(side, cmd, parms)
  511. Side *side;
  512. Obj *cmd, *parms;
  513. {
  514. }
  515.  
  516. static void
  517. do_multiple(side, cmd, parms)
  518. Side *side;
  519. Obj *cmd, *parms;
  520. {
  521.     repetition = c_number(car(parms));
  522.     multicmd = cdr(parms);
  523. }
  524.  
  525. static void
  526. do_save(side, cmd, parms)
  527. Side *side;
  528. Obj *cmd, *parms;
  529. {
  530.     if (!write_entire_game_state(saved_game_filename())) {
  531.     fprintf(stderr, "Save failed.\n");
  532.     }
  533. }
  534.  
  535. static void
  536. do_eval(side, cmd, parms)
  537. Side *side;
  538. Obj *cmd, *parms;
  539. {
  540.     interp_form(NULL, car(parms));
  541. }
  542.  
  543. static void
  544. do_help(side, cmd, parms)
  545. Side *side;
  546. Obj *cmd, *parms;
  547. {
  548.     printf("To look at help topics, type \"?<letter>\",\n");
  549.     printf("where 'n' and 'p' go to next and previous nodes\n");
  550. }
  551.  
  552. static void
  553. do_print(side, cmd, parms)
  554. Side *side;
  555. Obj *cmd, *parms;
  556. {
  557.     char *fname;
  558.     FILE *fp;
  559.  
  560.     if (parms != lispnil) {
  561.     if (stringp(car(parms))) {
  562.         fname = c_string(car(parms));
  563.         if ((fp = fopen(fname, "w")) != NULL) {
  564.         print_game_description_to_file(fp);
  565.         fclose(fp);
  566.         } else {
  567.         fprintf(stderr, "couldn't open \"%s\"\n", fname);
  568.         }
  569.     } else {
  570.         /* error, not a string */
  571.     }
  572.     } else {
  573.     print_game_description_to_file(stdout);
  574.     }
  575. }
  576.  
  577. static void
  578. do_memory(side, cmd, parms)
  579. Side *side;
  580. Obj *cmd, *parms;
  581. {
  582.     extern int grandtotmalloc;
  583.  
  584.     printf("%d bytes allocated.\n", grandtotmalloc);
  585. }
  586.  
  587. /* Exit immediately, no questions asked. */
  588.  
  589. static void
  590. do_quit(side, cmd, parms)
  591. Side *side;
  592. Obj *cmd, *parms;
  593. {
  594.     printf("Quitting.\n");
  595.     exit(0);
  596. }
  597.  
  598. #ifdef COMPILER
  599. static void
  600. do_compile(side, cmd, parms)
  601. Side *side;
  602. Obj *cmd, *parms;
  603. {
  604.     compile();
  605. }
  606. #endif /* COMPILER */
  607.  
  608. struct a_cmd {
  609.     char *cmd;
  610.     void (*fn) PROTO ((Side *side, Obj *cmd, Obj *parms));
  611. } cmdtable[] = {
  612.     { "debug", toggle_debug },
  613.     { "debugm", toggle_debugm },
  614.     { "debugg", toggle_debugg },
  615.     { "sides", list_sides },
  616.     { "units", list_units },
  617.     { "actors", list_actors },
  618.     { "cells", list_cells },
  619.     { "task", do_task_cmd },
  620.     { "fin", do_finish_turn },
  621.     { "finall", do_finish_all },
  622.     { "again", do_repeat },
  623.     { "*", do_multiple },
  624.     { "run", do_free_run },
  625.     { "save", do_save },
  626.     { "eval", do_eval },
  627.     { "help", do_help },
  628.     { "print", do_print },
  629.     { "memory", do_memory },
  630.     { "quit", do_quit },
  631. #ifdef COMPILER
  632.     { "compile", do_compile },
  633. #endif /* COMPILER */
  634.     { NULL, NULL }
  635. };
  636.  
  637. /* Try to find and execute an arbitrary command. */
  638.  
  639. static int
  640. do_cmd(side, cmd, parms)
  641. Side *side;
  642. Obj *cmd, *parms;
  643. {
  644.     struct a_cmd *cmdentry = cmdtable;
  645.     char *cmdstr;
  646.  
  647.     if (!symbolp(cmd)) return FALSE;
  648.     cmdstr = c_string(cmd);
  649.     while (cmdentry->cmd != NULL) {
  650.     if (strcmp(cmdstr, cmdentry->cmd) == 0) {
  651.         (*(cmdentry->fn))(side, cmd, parms);
  652.         return TRUE;
  653.     }
  654.     ++cmdentry;
  655.     }
  656.     return FALSE;
  657. }
  658.  
  659. static int
  660. do_action(side, unit, cmd, args)
  661. Side *side;
  662. Unit *unit;
  663. Obj *cmd, *args;
  664. {
  665.     int randomact = FALSE;
  666.     ActionDefn *actdefn = actiondefns;
  667.     char *cmdstr, *argstr;
  668.     char localbuf[BUFSIZE];
  669.     int i = 0, rslt;
  670.     Obj *rest;
  671.     Action action;
  672.  
  673.     if (!symbolp(cmd)) return FALSE;
  674.     cmdstr = c_string(cmd);
  675.     if (side == NULL) {
  676.     side = defaultside;
  677.     if (side == NULL) {
  678.         fprintf(stderr, "Using first side since no defaults avail\n");
  679.         side = sidelist->next;
  680.     }
  681.     }
  682.     if (unit == NULL) {
  683.     /* (think of something to do here) */
  684.     }
  685.     while (actdefn->name != NULL) {
  686.     if (strcmp(cmdstr, actdefn->name) == 0) {
  687.         memset(&action, 0, sizeof(Action));
  688.         action.type = actdefn->typecode;
  689.         /* Special option to generate random args to action. */
  690.         if (symbolp(car(args))
  691.         && strcmp("randomly", c_string(car(args))) == 0) {
  692.         args = cdr(args);
  693.         randomact = TRUE;
  694.         }
  695.         if (unit == NULL) {
  696.         if (randomact) {
  697.             while (!((unit = find_unit(xrandom(numunits))) != NULL
  698.                  && (unit->act != NULL || flip_coin()))
  699.                && probability(99));
  700.             if (unit == NULL) {
  701.             fprintf(stderr, "Can't find a unit to act!\n");
  702.             /* We're out of luck, just give up. */
  703.             return TRUE;
  704.             }
  705.         } else {
  706.             fprintf(stderr, "No unit to %s!\n", cmdstr);
  707.             /* *Command* *was* valid, just the args were bad. */
  708.             return TRUE;
  709.         }
  710.         }
  711.         /* Move args from list into action. */
  712.         argstr = actdefn->argtypes;
  713.         for (rest = args; rest != lispnil; rest = cdr(rest)) {
  714.         if (argstr[i] != '\0') {
  715.             action.args[i] = c_number(car(rest));
  716.         } else {
  717.             break;
  718.         }
  719.         ++i;
  720.         }
  721.         if (i != strlen(argstr)) {
  722.         if (randomact) {
  723.             make_plausible_random_args(argstr, i, &(action.args[0]),
  724.                            unit);
  725.         } else {
  726.             printf("Mismatched args!\n");
  727.             return TRUE;
  728.         }
  729.         }
  730.         sprintf(localbuf, "%s tries %s",
  731.             unit_desig(unit), action_desig(&action));
  732.         rslt = execute_action(unit, &action);
  733.         printf("%s - %s\n", localbuf, hevtdefns[rslt].name);
  734.         return TRUE;
  735.     }
  736.     ++actdefn;
  737.     }
  738.     return FALSE;
  739. }
  740.  
  741. /* Shut down displays - should be done before any sort of exit. */
  742.  
  743. void
  744. close_displays()
  745. {
  746.     Side *side;
  747.  
  748.     for_all_sides(side) {
  749.     if (active_display(side)) {
  750.         side->ui->active = FALSE;
  751.         printf("Display \"%s\" closed.\n", side->player->displayname);
  752.     }
  753.     }
  754. }
  755.  
  756. #ifdef __STDC__
  757. void
  758. notify(Side *side, char *format, ...)
  759. {
  760.     va_list ap;
  761.     char tmpnbuf[BUFSIZE];
  762.  
  763.     if (active_display(side)) {
  764.     va_start(ap, format);
  765.     vsprintf(tmpnbuf, format, ap);
  766.     va_end(ap);
  767.     /* Always capitalize first char of notice. */
  768.     if (islower(tmpnbuf[0])) tmpnbuf[0] = toupper(tmpnbuf[0]);
  769.     printf("To %s: %s\n", side_desig(side), tmpnbuf);
  770.     }
  771. }
  772. #else
  773. void
  774. notify(side, format, a1, a2, a3, a4, a5, a6, a7, a8)
  775. Side *side;
  776. char *format, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8;
  777. {
  778.     char tmpnbuf[BUFSIZE];
  779.  
  780.     if (active_display(side)) {
  781.     sprintf(tmpnbuf, format, a1, a2, a3, a4, a5, a6, a7, a8);
  782.     /* Always capitalize first char of notice. */
  783.     if (islower(tmpnbuf[0])) tmpnbuf[0] = toupper(tmpnbuf[0]);
  784.     printf("To %s: %s\n", side_desig(side), tmpnbuf);
  785.     }
  786. }
  787. #endif
  788.  
  789. /* (should count # of calls to inactive and non-displayed side...) */
  790.  
  791. void
  792. update_cell_display(side, x, y, rightnow)
  793. Side *side;
  794. int x, y;
  795. int rightnow;
  796. {
  797.     ++numcellupdatesperturn;
  798.     if (active_display(side)) {
  799.     ++numusefulcellupdatesperturn;
  800.     DGprintf("To %s: update view of %d,%d%s\n",
  801.          side_desig(side), x, y, (rightnow ? " (now)" : ""));
  802.     }
  803. }
  804.  
  805. /* This hook updates any display of the current turn/date, and any
  806.    other global info, as needed. */
  807.  
  808. void
  809. update_turn_display(side, rightnow)
  810. Side *side;
  811. int rightnow;
  812. {
  813.     long secs;
  814.     time_t xxx;
  815.  
  816.     if (active_display(side)) {
  817.     time(&xxx);
  818.     secs = idifftime(xxx, skelturnstart);
  819.     printf("To %s: update to turn %d (%ld seconds since last)",
  820.            side_desig(side), g_turn(), secs);
  821.     DGprintf("%s", (rightnow ? " (now)" : ""));
  822.     printf("\n");
  823.     printf("%d cell updates, %d useful\n",
  824.            numcellupdatesperturn, numusefulcellupdatesperturn);
  825.     numcellupdatesperturn = numusefulcellupdatesperturn = 0;
  826.     skelturnstart = xxx;
  827.     --freerunturns;
  828.     if (rightnow) fflush(stdout);
  829.     }
  830. }
  831.  
  832. void
  833. update_action_display(side, rightnow)
  834. Side *side;
  835. int rightnow;
  836. {
  837.     if (active_display(side) && DebugG) {
  838.     printf("To %s: ready to act\n", side_desig(side));
  839.     }
  840. }
  841.  
  842. void
  843. update_action_result_display(side, unit, rslt, rightnow)
  844. Side *side;
  845. Unit *unit;
  846. int rslt, rightnow;
  847. {
  848.     if (active_display(side) && DebugG) {
  849.     printf("To %s: %s action result is %s\n",
  850.            side_desig(side), unit_desig(unit), hevtdefns[rslt].name);
  851.     }
  852. }
  853.  
  854. /* This is for animation of fire-at actions. */
  855.  
  856. void
  857. update_fire_at_display(side, unit, unit2, m, rightnow)
  858. Side *side;
  859. Unit *unit, *unit2;
  860. int m, rightnow;
  861. {
  862. }
  863.  
  864. /* This is for animation of fire-into actions. */
  865.  
  866. void
  867. update_fire_into_display(side, unit, x, y, z, m, rightnow)
  868. Side *side;
  869. Unit *unit;
  870. int x, y, z, m, rightnow;
  871. {
  872. }
  873.  
  874. void
  875. update_event_display(side, hevt, rightnow)
  876. Side *side;
  877. HistEvent *hevt;
  878. int rightnow;
  879. {
  880.     if (active_display(side)) {
  881.     switch (hevt->type) {
  882.       case H_SIDE_LOST:
  883.         printf("%s lost!\n", side_desig(side_n(hevt->data[0])));
  884.         break;
  885.       case H_SIDE_WON:
  886.         printf("%s won!\n",  side_desig(side_n(hevt->data[0])));
  887.         break;
  888.       default:
  889.         DGprintf("To %s: event %s %d\n",
  890.              side_desig(side), hevtdefns[hevt->type].name,
  891.              hevt->data[0]);
  892.     }
  893.     }
  894. }
  895.  
  896. void
  897. update_all_progress_displays(str, s)
  898. char *str;
  899. int s;
  900. {
  901. }
  902.  
  903. /* This hook should update the side's view of the given side, no matter
  904.    who it belongs to. */
  905.  
  906. void
  907. update_side_display(side, side2, rightnow)
  908. Side *side, *side2;
  909. int rightnow;
  910. {
  911.     char *side2desc = copy_string(side_desig(side2));
  912.  
  913.     if (active_display(side) && DebugG) {
  914.     printf("To %s: update side %s%s\n",
  915.            side_desig(side), side2desc, (rightnow ? " (now)" : ""));
  916.     }
  917. }
  918.  
  919. /* This hook should update the side's view of the given unit, no matter
  920.    who it belongs to. */
  921.  
  922. void
  923. update_unit_display(side, unit, rightnow)
  924. Side *side;
  925. Unit *unit;
  926. int rightnow;
  927. {
  928.     if (active_display(side) && DebugG) {
  929.     printf("To %s: update unit %s%s\n",
  930.            side_desig(side), unit_desig(unit), (rightnow ? " (now)" : ""));
  931.     }
  932. }
  933.  
  934. void
  935. update_unit_acp_display(side, unit, rightnow)
  936. Side *side;
  937. Unit *unit;
  938. int rightnow;
  939. {
  940.     if (active_display(side) && DebugG) {
  941.     printf("To %s: update unit %s acp%s\n",
  942.            side_desig(side), unit_desig(unit), (rightnow ? " (now)" : ""));
  943.     }
  944. }
  945.  
  946. /* This hook updates any realtime clock displays.  If the game does not
  947.    have any realtime constraints, this will never be called. */
  948.  
  949. void
  950. update_clock_display(side, rightnow)
  951. Side *side;
  952. int rightnow;
  953. {
  954.     if (active_display(side) && DebugG) {
  955.     printf("To %s: %d secs this turn, %d total\n",
  956.            side_desig(side), side->turntimeused, side->totaltimeused);
  957.     /* also display total game clock */
  958.     }
  959. }
  960.  
  961. void
  962. update_message_display(side, sender, str, rightnow)
  963. Side *side, *sender;
  964. char *str;
  965. int rightnow;
  966. {
  967. }
  968.  
  969. void
  970. update_everything()
  971. {
  972.     printf("Update everything!\n");
  973. }
  974.  
  975. /* Generate a description of all the user input that is possible. */
  976.  
  977. static void
  978. describe_commands(arg, key, buf)
  979. int arg;
  980. char *key, *buf;
  981. {
  982.     struct a_cmd *cmdentry;
  983.  
  984.     for (cmdentry = cmdtable; cmdentry->cmd != NULL; ++cmdentry) {
  985.     strcat(buf, cmdentry->cmd);
  986.     strcat(buf, "\n");
  987.     }
  988. }
  989.  
  990. static void
  991. interpret_help(side, topic)
  992. Side *side;
  993. char *topic;
  994. {
  995.     HelpNode *node;
  996.  
  997.     if (side == NULL) side = defaultside;
  998.     if (side == NULL) {
  999.     fprintf(stderr, "no side to help?\n");
  1000.     return;
  1001.     }
  1002.     if (curhelpnode == NULL) {
  1003.     add_help_node("commands", describe_commands, 0, firsthelpnode);
  1004.     curhelpnode = firsthelpnode;
  1005.     }
  1006.     switch (topic[0]) {
  1007.       case 'n':
  1008.     curhelpnode = curhelpnode->next;
  1009.     break;
  1010.       case 'p':
  1011.     curhelpnode = curhelpnode->prev;
  1012.     break;
  1013.       case 'a':
  1014.     for (node = firsthelpnode->next; node != firsthelpnode; node = node->next) {
  1015.         show_help(side, node);
  1016.     }
  1017.     return; /* don't show cur help node too */
  1018.       case '\0':
  1019.     /* Note that no topic char equals '\0', so will come here. */
  1020.       default:
  1021.     curhelpnode = firsthelpnode;
  1022.     break;
  1023.     }
  1024.     show_help(side, curhelpnode);
  1025. }
  1026.  
  1027. /* Spew out the entire text of the current help node. */
  1028.  
  1029. static void
  1030. show_help(side, helpnode)
  1031. Side *side;
  1032. HelpNode *helpnode;
  1033. {
  1034.     int linelen, skipchar;
  1035.     char *linebegin = get_help_text(helpnode), *lineend;
  1036.  
  1037.     printf("Topic: %s\n", helpnode->key);
  1038.     while (*linebegin != '\0') {
  1039.     skipchar = 0;
  1040.     lineend = (char *) strchr(linebegin, '\n');
  1041.     if (lineend) skipchar = 1;
  1042.     linelen = (lineend ? lineend - linebegin : strlen(linebegin));
  1043.     if (linelen > 75) linelen = 75;
  1044.     strncpy(spbuf, linebegin, linelen);
  1045.     spbuf[linelen] = '\0';
  1046.     printf("%s\n", spbuf);
  1047.     linebegin += linelen + skipchar;
  1048.     }
  1049. }
  1050.  
  1051. /* This reports progress in reading GDL files. */
  1052.  
  1053. void
  1054. announce_read_progress()
  1055. {
  1056. }
  1057.  
  1058. /* This is used for initialization steps that take a long time. */
  1059.  
  1060. int linemiddle = FALSE;
  1061.  
  1062. void
  1063. announce_lengthy_process(msg)
  1064. char *msg;
  1065. {
  1066.     printf("%s; ", msg);
  1067.     fflush(stdout);
  1068.     linemiddle = TRUE;
  1069. }
  1070.  
  1071. /* Update the progress, expressing it as a percentage done. */
  1072.  
  1073. void
  1074. announce_progress(percentdone)
  1075. int percentdone;
  1076. {
  1077.     printf(" %d%%", percentdone);
  1078.     fflush(stdout);
  1079.     linemiddle = TRUE;
  1080. }
  1081.  
  1082. /* Announce the end of the lengthy process. */
  1083.  
  1084. void
  1085. finish_lengthy_process()
  1086. {
  1087.     printf(" done.\n");
  1088.     linemiddle = FALSE;
  1089. }
  1090.  
  1091. int
  1092. #ifdef __STDC__
  1093. schedule_movie(Side *side, enum movie_type movie, ...)
  1094. #else
  1095. schedule_movie(side, movie)
  1096. Side *side;
  1097. enum movie_type movie;
  1098. #endif
  1099. {
  1100.     return FALSE;
  1101. }
  1102.  
  1103. void
  1104. play_movies(sidemask)
  1105. SideMask sidemask;
  1106. {
  1107. }
  1108.  
  1109. void
  1110. flush_display_buffers(side)
  1111. Side *side;
  1112. {
  1113.     if (active_display(side) && DebugG) {
  1114.     printf("To %s: flush display buffers\n", side_desig(side));
  1115.     }
  1116. }
  1117.  
  1118. /* An init error needs to have the command re-run. */
  1119.  
  1120. void
  1121. low_init_error(str)
  1122. char *str;
  1123. {
  1124.     if (linemiddle) printf("\n");
  1125.     fprintf(stderr, "Error: %s.\n", str);
  1126.     fflush(stderr);
  1127. }
  1128.  
  1129. /* A warning just gets displayed, no other action is taken. */
  1130.  
  1131. void
  1132. low_init_warning(str)
  1133. char *str;
  1134. {
  1135.     if (linemiddle) printf("\n");
  1136.     fprintf(stdout, "Warning: %s.\n", str);
  1137.     fflush(stdout);
  1138. }
  1139.  
  1140. /* A run error is fatal. */
  1141.  
  1142. void
  1143. low_run_error(str)
  1144. char *str;
  1145. {
  1146.     if (linemiddle) fprintf(stderr, "\n");
  1147.     fprintf(stderr, "Error: %s.\n", str);
  1148.     fflush(stderr);
  1149.     exit(1);
  1150. }
  1151.  
  1152. /* Runtime warnings are for when it's important to bug the players,
  1153.    usually a problem with Xconq or a game design. */
  1154.  
  1155. void
  1156. low_run_warning(str)
  1157. char *str;
  1158. {
  1159.     if (linemiddle) printf("\n");
  1160.     fprintf(stdout, "Warning: %s.\n", str);
  1161.     fflush(stdout);
  1162. }
  1163.  
  1164. void
  1165. printlisp(obj)
  1166. Obj *obj;
  1167. {
  1168.     fprintlisp(stdout, obj);
  1169. }
  1170.